// Include Files
#include "Matrix.h"

#include <math.h>

/////////////////////////////////////////////////////////////////////////////////////
// matrix_t Definitions

IE::matrix_t IE::Matrix()
{
	matrix_t ret;

	ret.row[0] = Vector(1.0f, 0.0f, 0.0f, 0.0f);
	ret.row[1] = Vector(0.0f, 1.0f, 0.0f, 0.0f);
	ret.row[2] = Vector(0.0f, 0.0f, 1.0f, 0.0f);
	ret.row[3] = Vector(0.0f, 0.0f, 0.0f, 1.0f);

	return ret;
}

IE::matrix_t IE::MatrixMul( matrix_t const &_lhs, matrix_t const &_rhs )
{
	matrix_t ret = Matrix();

	vector_t v0, v1, v2, v3, v4, v5;
	for( int_t i = 0; i < 4; ++i )
	{
		v0 = VectorShuffle<VEC_SHUFFLE_MASK(0, 0, 0, 0)>(_lhs.row[i], _lhs.row[i]);
		v0 = VectorMul(v0, _rhs.row[0] );

		v1 = VectorShuffle<VEC_SHUFFLE_MASK(1, 1, 1, 1)>(_lhs.row[i], _lhs.row[i]);
		v1 = VectorMul(v1, _rhs.row[1] );

		v2 = VectorShuffle<VEC_SHUFFLE_MASK(2, 2, 2, 2)>(_lhs.row[i], _lhs.row[i]);
		v2 = VectorMul(v2, _rhs.row[2] );

		v3 = VectorShuffle<VEC_SHUFFLE_MASK(3, 3, 3, 3)>(_lhs.row[i], _lhs.row[i]);
		v3 = VectorMul(v3, _rhs.row[3] );

		v4 = VectorAdd(v0, v1);
		v5 = VectorAdd(v2, v3);
		ret.row[i] = VectorAdd(v4, v5);
	}

	return ret;
}

IE::matrix_t IE::MatrixTranslation( float_t _fX, float_t _fY, float_t _fZ )
{
	matrix_t ret;

	ret.row[0] = Vector(1.0f, 0.0f, 0.0f, 0.0f);
	ret.row[1] = Vector(0.0f, 1.0f, 0.0f, 0.0f);
	ret.row[2] = Vector(0.0f, 0.0f, 1.0f, 0.0f);
	ret.row[3] = Vector(_fX,  _fY,  _fZ,  1.0f);

	return ret;
}

IE::matrix_t IE::MatrixRotationX( float_t _fAngle )
{
	float_t fSin = sin(_fAngle);
	float_t fCos = cos(_fAngle);

	matrix_t ret;

	ret.row[0] = Vector( 1.0f,  0.0f,  0.0f,  0.0f);
	ret.row[1] = Vector( 0.0f,  fCos, -fSin,  0.0f);
	ret.row[2] = Vector( 0.0f,  fSin,  fCos,  0.0f);
	ret.row[3] = Vector( 0.0f,  0.0f,  0.0f,  1.0f);

	return ret;
}

IE::matrix_t IE::MatrixRotationY( float_t _fAngle )
{
	float_t fSin = sin(_fAngle);
	float_t fCos = cos(_fAngle);

	matrix_t ret;

	ret.row[0] = Vector( fCos,  0.0f,  fSin,  0.0f);
	ret.row[1] = Vector( 0.0f,  1.0f,  0.0f,  0.0f);
	ret.row[2] = Vector(-fSin,  0.0f,  fCos,  0.0f);
	ret.row[3] = Vector( 0.0f,  0.0f,  0.0f,  1.0f);

	return ret;
}

IE::matrix_t IE::MatrixRotationZ( float_t _fAngle )
{
	float_t fSin = sin(_fAngle);
	float_t fCos = cos(_fAngle);

	matrix_t ret;

	ret.row[0] = Vector( fCos, -fSin,  0.0f,  0.0f);
	ret.row[1] = Vector( fSin,  fCos,  0.0f,  0.0f);
	ret.row[2] = Vector( 0.0f,  0.0f,  1.0f,  0.0f);
	ret.row[3] = Vector( 0.0f,  0.0f,  0.0f,  1.0f);

	return ret;
}
